#include "StdAfx.h"
#include "CConsoleSystem.h"
#include "IConsoleScreen.h"
#include "CCommandDictionary.h"
#include "CCommand.h"
#include "CCommandHistory.h"
#include "CArgumentList.h"
#include "ConsoleObject.h"
#include "Tokenizer.h"


CConsoleSystem::CConsoleSystem()
{
	m_pConsoleScreen = NULL;
	m_pCommandHistory = NULL;
}


bool CConsoleSystem::Initialize( IConsoleScreen * pConsoleScreen, CCommandHistory *pHistory )
{
	m_pConsoleScreen = pConsoleScreen;
	m_pCommandHistory = pHistory;

	pConsoleScreen->Print("Console command system 2.0");
	pConsoleScreen->Print("Author		: tien(lovelytien@gmail.com)");
	pConsoleScreen->Print("Last update	: 2009-08-18");
	pConsoleScreen->PrintSeparation();
	pConsoleScreen->PrintLinefeed();

	return true;
}

void PrintVerboseTokenList( IConsoleScreen *pScreen, const std::list<csString> & tokens )
{
	csString strTokensDebugMessage = "Token list: ";
	std::list<csString>::const_iterator iter = tokens.begin();
	for ( ; iter != tokens.end(); ++iter )
	{
		strTokensDebugMessage += "<" + (*iter) + "> ";
	}
	pScreen->PrintVerbose(strTokensDebugMessage);
}

bool CConsoleSystem::Execute( const csString & strCommandLine )
{
	if ( strCommandLine.empty() )
		return false;

	//_SplitCommand();

	std::list<csString> strTokens;
	Tokenizer( strTokens, strCommandLine, " ", "\"\'" );

	if ( strTokens.empty() )
		return false;

	// insert to command history
	if ( m_pCommandHistory )
		m_pCommandHistory->Push( strCommandLine );


	PrintVerboseTokenList( m_pConsoleScreen, strTokens );

	csString strCommand = strTokens.front();
	strTokens.pop_front();

	bool bResult = false;
	CCommand *pCommand = GetConsleDictionary().GetCommand( strCommand );
	if ( pCommand )
	{
		CArgumentList args;
		args.m_Arguments.resize( strTokens.size() );
		std::copy( strTokens.begin(), strTokens.end(), args.m_Arguments.begin() );

		bResult = Execute( pCommand, args );
	}
	else
	{
		m_pConsoleScreen->PrintError( "unknown command." );
		bResult = false;
	}

	if (bResult)
		m_pConsoleScreen->Print( "process success." );
	else
		m_pConsoleScreen->PrintError( "process failure." );

	m_pConsoleScreen->PrintLinefeed();

	return bResult;
}

bool CConsoleSystem::Execute( CCommand *pCommand, const CArgumentList & args )
{
	try
	{
		return pCommand->Execute( m_pConsoleScreen, args );
	}
	catch( SStringToAnyTypeCastException & e )
	{
		m_pConsoleScreen->PrintError( 
			"cannot convert \'"  + e.strSrcString + "\' to " + e.strDstTypeName + " type." );
	}
	catch( ... )
	{
		m_pConsoleScreen->PrintError( "unknown runtime error!" );
	}

	return false;

}
